package com.atguigu.yuntai.govern.service.impl;

import com.atguigu.yuntai.common.config.ApplicationContextProvider;
import com.atguigu.yuntai.govern.entity.TableInfo;
import com.atguigu.yuntai.govern.entity.*;
import com.atguigu.yuntai.govern.judger.Judger;
import com.atguigu.yuntai.govern.service.*;
import com.baomidou.dynamic.datasource.annotation.DS;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ScoringServiceImpl implements ScoringService {

    @Autowired
    GovernanceOptionService governanceOptionService;

    @Autowired
    GovernanceTypeService governanceTypeService;

    @Autowired
    GovernanceDetailService governanceDetailService;

    @Autowired
    GovernanceTableService governanceTableService;

    @Autowired
    GovernanceUserService governanceUserService;

    @Autowired
    GovernanceGlobalService governanceGlobalService;

    public void calcScoring(List<TableInfo> tableInfoList, String busiDate) {

        log.info("-------查询治理项和治理类型------");

        //查询治理项清单
        Map<String, GovernanceOption> governanceOptionMap = governanceOptionService.getGovernanceOptionMap();

        //查询治理项类别
        Map<String, GovernanceType> governanceTypeMap = governanceTypeService.getGovernanceTypeMap();

        log.info("-------初始化评分器------");
        List<Judger> judgerList = initJudgerList(governanceOptionMap);

        //获得表治理结果
        List<GovernanceDetail> governanceDetailAllList = new ArrayList();
        List<GovernanceTable> governanceTableList = new ArrayList<>();

        for (TableInfo tableInfo : tableInfoList) {
            Long problemNum = 0L;
            List<GovernanceDetail> governanceDetailForTableList = new ArrayList();
            for (Judger judger : judgerList) {
                GovernanceDetail governanceDetail = judger.judge(tableInfo, busiDate);
                governanceDetail.setBusiDate(busiDate);
                governanceDetail.setCreateTime(new Date());
                governanceDetail.setTecOwnerUserId(tableInfo.getTecOwnerUserId());
                governanceDetailForTableList.add(governanceDetail);

                //每项分数低于1 则增加问题项
                if (governanceDetail.getGovernanceScore().compareTo(BigDecimal.ONE) < 0) {
                    problemNum++;
                }

            }
            GovernanceTable governanceTable = calcScoreForTable(governanceDetailForTableList, tableInfo, governanceOptionMap, governanceTypeMap);
            governanceTable.setProblemNum(problemNum);
            governanceTable.setBusiDate(busiDate);
            governanceTable.setCreateTime(new Date());

            governanceTableList.add(governanceTable);
            governanceDetailAllList.addAll(governanceDetailForTableList);
        }
        log.info("--------把治理项明细保存 -----------");
        governanceDetailService.saveOrUpdateBatch(governanceDetailAllList);

        log.info("--------计算各个表的治理分数 -----------");
        //根据各个表的权重 计算总分数
        calcTableScoreByWeight(governanceTableList);
        // 分数核算到表中
        governanceTableService.saveOrUpdateBatch(governanceTableList);

        log.info("--------开始对个人治理分进行计算-----------");
        List<GovernanceUser> governanceUserList = calcUserScore(governanceTableList);
        governanceUserService.saveOrUpdateBatch(governanceUserList);

        log.info("--------开始对全局治理分进行计算-----------");
        GovernanceGlobal governanceGlobal = calcGlobalScore(governanceTableList);
        governanceGlobalService.saveOrUpdate(governanceGlobal);

    }

    //初始化评分器
    public List<Judger> initJudgerList(Map<String, GovernanceOption> governanceOptionMap) {

        List judgerList = new ArrayList();
        for (String optionCode : governanceOptionMap.keySet()) {
            Judger judger = ApplicationContextProvider.getBean(optionCode, Judger.class);
            judgerList.add(judger);
        }
        return judgerList;

    }

    public GovernanceTable calcScoreForTable(List<GovernanceDetail> governanceDetailForTableList, TableInfo tableInfo, Map<String, GovernanceOption> governanceOptionMap, Map<String, GovernanceType> governanceTypeMap) {
        GovernanceTable governanceTable = new GovernanceTable();
        Long tableSize = tableInfo.getTableSize();

        governanceTable.setTableName(tableInfo.getTableName());
        governanceTable.setSchemaName(tableInfo.getSchemaName());
        governanceTable.setTecOwnerUserId(tableInfo.getTecOwnerUserId());

        for (GovernanceDetail governanceDetail : governanceDetailForTableList) {

            String optionType = governanceDetail.getOptionType();
            //  类别分数/类别个数 *100
            if (optionType.equals("SPEC")) {
                governanceTable.setScoreSpec(governanceDetail.getGovernanceScore().add(governanceTable.getScoreSpec()));
                governanceTable.setCountSpec(governanceTable.getCountSpec() + 1);
            } else if (optionType.equals("STORAGE")) {
                governanceTable.setScoreStorage(governanceDetail.getGovernanceScore().add(governanceTable.getScoreStorage()));
                governanceTable.setCountStorage(governanceTable.getCountStorage() + 1);
            } else if (optionType.equals("CALC")) {
                governanceTable.setScoreCalc(governanceDetail.getGovernanceScore().add(governanceTable.getScoreCalc()));
                governanceTable.setCountCalc(governanceTable.getCountCalc() + 1);
            } else if (optionType.equals("QUALITY")) {
                governanceTable.setScoreQuality(governanceDetail.getGovernanceScore().add(governanceTable.getScoreQuality()));
                governanceTable.setCountQuality(governanceTable.getCountQuality() + 1);
            } else if (optionType.equals("SECURITY")) {
                governanceTable.setScoreSecurity(governanceDetail.getGovernanceScore().add(governanceTable.getScoreSecurity()));
                governanceTable.setCountSecurity(governanceTable.getCountSecurity() + 1);
            }

        }

        //  类别分数/类别个数 *100
        governanceTable.setScoreSpec(governanceTable.getScoreSpec().divide(BigDecimal.valueOf(governanceTable.getCountSpec()), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));

        governanceTable.setScoreStorage(governanceTable.getScoreStorage().divide(BigDecimal.valueOf(governanceTable.getCountStorage()), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
        governanceTable.setScoreQuality(governanceTable.getScoreQuality().divide(BigDecimal.valueOf(governanceTable.getCountQuality()), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
        governanceTable.setScoreCalc(governanceTable.getScoreCalc().divide(BigDecimal.valueOf(governanceTable.getCountCalc()), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
        governanceTable.setScoreSecurity(governanceTable.getScoreSecurity().divide(BigDecimal.valueOf(governanceTable.getCountSecurity()), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));

        BigDecimal specTypeWeight = governanceTypeMap.get("SPEC").getTypeWeight();
        BigDecimal storeTypeWeight = governanceTypeMap.get("STORAGE").getTypeWeight();
        BigDecimal calcTypeWeight = governanceTypeMap.get("CALC").getTypeWeight();
        BigDecimal quaTypeWeight = governanceTypeMap.get("QUALITY").getTypeWeight();
        BigDecimal secTypeWeight = governanceTypeMap.get("SECURITY").getTypeWeight();

        BigDecimal scoreTypeWeight = BigDecimal.ZERO;
        scoreTypeWeight = scoreTypeWeight.add(governanceTable.getScoreSpec().multiply(specTypeWeight));
        scoreTypeWeight = scoreTypeWeight.add(governanceTable.getScoreStorage().multiply(storeTypeWeight));
        scoreTypeWeight = scoreTypeWeight.add(governanceTable.getScoreCalc().multiply(calcTypeWeight));
        scoreTypeWeight = scoreTypeWeight.add(governanceTable.getScoreQuality().multiply(quaTypeWeight));
        scoreTypeWeight = scoreTypeWeight.add(governanceTable.getScoreSecurity().multiply(secTypeWeight));

        governanceTable.setScoreWithTypeWeight(scoreTypeWeight);
        // 按表计算权重
        //  本表权重= 字节大小的立方根 // tableSize 不足1G的视为1个G

        long tableSizeForWeight = Math.max(tableSize, 1024 * 1024 * 1024);

        BigDecimal tableWeight = BigDecimal.valueOf(Math.cbrt(tableSizeForWeight));
        governanceTable.setTableWeight(tableWeight);

        governanceTable.setChargeDeptId(tableInfo.getDeptId());

        return governanceTable;
    }

    //根据表权重计算表分数
    public List<GovernanceTable> calcTableScoreByWeight(List<GovernanceTable> governanceTableList) {
        BigDecimal sumWeight = BigDecimal.ZERO;

        for (GovernanceTable governanceTable : governanceTableList) {
            BigDecimal tableWeight = governanceTable.getTableWeight();
            sumWeight = sumWeight.add(tableWeight);
        }

        return governanceTableList;
    }

    //根据表治理明细 统计个人分数
    public List<GovernanceUser> calcUserScore(List<GovernanceTable> governanceTableList) {

        Map<Long, List<GovernanceTable>> governanceTableByUidMap = governanceTableList.stream().collect(Collectors.groupingBy(GovernanceTable::getTecOwnerUserId));

        List<GovernanceUser> governanceUserList = new ArrayList<>();

        for (List<GovernanceTable> tableForUserList : governanceTableByUidMap.values()) {
            GovernanceUser governanceUser = new GovernanceUser();

            for (GovernanceTable governanceTable : tableForUserList) {

                governanceUser.setProblemNum(governanceUser.getProblemNum() + governanceTable.getProblemNum());
                //   Σ分数*权重
                governanceUser.setScoreQuality(governanceUser.getScoreQuality().add(governanceTable.getScoreQuality().multiply(governanceTable.getTableWeight())));
                governanceUser.setScoreStorage(governanceUser.getScoreStorage().add(governanceTable.getScoreStorage().multiply(governanceTable.getTableWeight())));
                governanceUser.setScoreCalc(governanceUser.getScoreCalc().add(governanceTable.getScoreCalc().multiply(governanceTable.getTableWeight())));
                governanceUser.setScoreSecurity(governanceUser.getScoreSecurity().add(governanceTable.getScoreSecurity().multiply(governanceTable.getTableWeight())));
                governanceUser.setScoreSpec(governanceUser.getScoreSpec().add(governanceTable.getScoreSpec().multiply(governanceTable.getTableWeight())));
                governanceUser.setScore(governanceUser.getScore().add(governanceTable.getScoreWithTypeWeight().multiply(governanceTable.getTableWeight())));
                governanceUser.setSumWeight(governanceUser.getSumWeight().add(governanceTable.getTableWeight()));
                governanceUser.setChargeTecUserId(governanceTable.getTecOwnerUserId());
                governanceUser.setBusiDate(governanceTable.getBusiDate());
                governanceUser.setCreateTime(new Date());
            }

            // Σ分数*权重 / 总权重
            governanceUser.setScoreQuality(governanceUser.getScoreQuality().divide(governanceUser.getSumWeight(), 2, RoundingMode.HALF_UP));
            governanceUser.setScoreStorage(governanceUser.getScoreStorage().divide(governanceUser.getSumWeight(), 2, RoundingMode.HALF_UP));
            governanceUser.setScoreCalc(governanceUser.getScoreCalc().divide(governanceUser.getSumWeight(), 2, RoundingMode.HALF_UP));
            governanceUser.setScoreSecurity(governanceUser.getScoreSecurity().divide(governanceUser.getSumWeight(), 2, RoundingMode.HALF_UP));
            governanceUser.setScoreSpec(governanceUser.getScoreSpec().divide(governanceUser.getSumWeight(), 2, RoundingMode.HALF_UP));
            governanceUser.setScore(governanceUser.getScore().divide(governanceUser.getSumWeight(), 2, RoundingMode.HALF_UP));

            governanceUserList.add(governanceUser);

        }

        return governanceUserList;
    }

    /**
     * 根据标治理明细  统计全局分数
     */
    public GovernanceGlobal calcGlobalScore(List<GovernanceTable> governanceTableList) {

        GovernanceGlobal governanceGlobal = new GovernanceGlobal();

        for (GovernanceTable governanceTable : governanceTableList) {

            governanceGlobal.setProblemNum(governanceGlobal.getProblemNum() + governanceTable.getProblemNum());
            //   Σ分数*权重
            governanceGlobal.setScoreQuality(governanceGlobal.getScoreQuality().add(governanceTable.getScoreQuality().multiply(governanceTable.getTableWeight())));
            governanceGlobal.setScoreStorage(governanceGlobal.getScoreStorage().add(governanceTable.getScoreStorage().multiply(governanceTable.getTableWeight())));
            governanceGlobal.setScoreCalc(governanceGlobal.getScoreCalc().add(governanceTable.getScoreCalc().multiply(governanceTable.getTableWeight())));
            governanceGlobal.setScoreSecurity(governanceGlobal.getScoreSecurity().add(governanceTable.getScoreSecurity().multiply(governanceTable.getTableWeight())));
            governanceGlobal.setScoreSpec(governanceGlobal.getScoreSpec().add(governanceTable.getScoreSpec().multiply(governanceTable.getTableWeight())));
            governanceGlobal.setScore(governanceGlobal.getScore().add(governanceTable.getScoreWithTypeWeight().multiply(governanceTable.getTableWeight())));
            governanceGlobal.setSumWeight(governanceGlobal.getSumWeight().add(governanceTable.getTableWeight()));

            governanceGlobal.setBusiDate(governanceTable.getBusiDate());
            governanceGlobal.setCreateTime(new Date());
        }

        // Σ分数*权重 / 总权重
        governanceGlobal.setScoreQuality(governanceGlobal.getScoreQuality().divide(governanceGlobal.getSumWeight(), 2, RoundingMode.HALF_UP));
        governanceGlobal.setScoreStorage(governanceGlobal.getScoreStorage().divide(governanceGlobal.getSumWeight(), 2, RoundingMode.HALF_UP));
        governanceGlobal.setScoreCalc(governanceGlobal.getScoreCalc().divide(governanceGlobal.getSumWeight(), 2, RoundingMode.HALF_UP));
        governanceGlobal.setScoreSecurity(governanceGlobal.getScoreSecurity().divide(governanceGlobal.getSumWeight(), 2, RoundingMode.HALF_UP));
        governanceGlobal.setScoreSpec(governanceGlobal.getScoreSpec().divide(governanceGlobal.getSumWeight(), 2, RoundingMode.HALF_UP));
        governanceGlobal.setScore(governanceGlobal.getScore().divide(governanceGlobal.getSumWeight(), 2, RoundingMode.HALF_UP));
        governanceGlobal.setTableNum(governanceTableList.size() + 0L);
        return governanceGlobal;
    }

}




